ByteFisher AI 编程实战(十八):AI Agent 入门——从对话到自主决策

从这一篇开始,我们进入 AI 编程的深水区——AI Agent。如果说前面的 AI 工具是”问一句答一句”,Agent 则是能自主规划、调用工具、完成任务的智能体。

一、什么是 AI Agent

AI Agent 是指能够自主感知环境、制定计划、执行行动的 AI 系统。和前面介绍的 AI 工具最大的区别是:它是主动的,而不是被动的。

能力 普通 LLM AI Agent
交互方式 一问一答 多轮自主决策
工具使用 调用 API、执行代码、读写文件
规划 分解复杂任务、按步骤执行
反馈循环 观察结果 → 调整策略
记忆 无(仅当前对话) 可存取长期记忆

二、ReAct 模式——思考-行动-观察

Agent 的核心运行模式叫做 ReAct(Reasoning + Acting)。每一次循环都是”思考→行动→观察”的迭代:

1
2
3
4
5
6
7
8
9
用户:帮我查北京明天的天气,定个闹钟提醒带伞

Agent 思考:需要查天气,根据结果决定是否设置提醒
Agent 行动:调用 get_weather(beijing, tomorrow)
环境反馈:{"condition": "rain", "temp": 22}
Agent 观察:明天下雨,需要带伞
Agent 行动:set_reminder("带伞", "2025-06-09 08:00")
环境反馈:{"success": true}
Agent 回答:已查天气(明天下雨,22°C)并设置了明早 8 点带伞提醒。

这个过程不是预设的脚本——每一步的”思考”都是 LLM 实时推理的结果,因此 Agent 能处理从未见过的场景。

ReAct 的 Prompt 模板

如果你手动实现一个简单的 Agent,核心 Prompt 长这样:

1
2
3
4
5
6
7
8
9
10
11
12
你是一个智能助手,可以通过调用工具完成任务。
每轮请按以下格式输出:

思考:分析当前状态,决定下一步做什么
行动:{"tool": "工具名", "args": {...}}

当任务完成时,输出:
最终答案:...

可用工具:
- get_weather(city, date): 获取天气
- set_reminder(text, time): 设置提醒

三、Function Calling——LLM 调用工具的标准接口

3.1 定义工具

要实现 Agent,先定义 LLM 可调用的工具:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名,如 '北京'"},
"date": {"type": "string", "description": "日期,格式 YYYY-MM-DD"}
},
"required": ["city", "date"]
}
}
}]

3.2 Agent 运行循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import json
import openai

def agent_loop(user_input: str, max_steps: int = 10):
messages = [{"role": "user", "content": user_input}]

for step in range(max_steps):
response = openai.chat.completions.create(
model="deepseek-chat",
messages=messages,
tools=tools
)

msg = response.choices[0].message
messages.append(msg)

# 如果 LLM 没有调用工具,说明任务完成
if not msg.tool_calls:
return msg.content

# 执行每个工具调用
for tool_call in msg.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)

# 执行实际的工具函数
result = execute_tool(func_name, func_args)

messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False)
})

return "达到最大步数限制,任务可能未完成"

3.3 执行工具

1
2
3
4
5
6
7
8
9
def execute_tool(name: str, args: dict):
if name == "get_weather":
# 调用真实天气 API 或返回模拟数据
return {"condition": "rain", "temp": 22, "humidity": 80}
elif name == "set_reminder":
# 设置系统提醒
return {"success": True, "id": "remind_001"}
else:
return {"error": f"未知工具: {name}"}

四、Agent 实战:代码分析助手

构建一个能分析 GitHub 项目的 Agent:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
tools = [
{
"name": "read_file",
"description": "读取项目文件内容",
"parameters": {
"type": "object",
"properties": {
"path": {"type": "string"}
},
"required": ["path"]
}
},
{
"name": "list_directory",
"description": "列出目录中的文件",
"parameters": {
"type": "object",
"properties": {
"path": {"type": "string"}
},
"required": ["path"]
}
},
{
"name": "search_code",
"description": "在项目中搜索代码",
"parameters": {
"type": "object",
"properties": {
"pattern": {"type": "string"},
"path": {"type": "string"}
},
"required": ["pattern"]
}
}
]

用户问”这个项目的依赖注入是怎么配置的?”,Agent 会自动:

  1. list_directory("src") → 找到项目结构
  2. read_file("src/di/container.ts") → 读取依赖配置
  3. search_code("Injectable") → 搜索装饰器使用
  4. 综合分析后给出完整答案

五、安全边界

Agent 的自主性越强,安全风险就越大:

风险 防护措施 代码实现
工具滥用 设置 max_steps 上限 for step in range(10)
权限过大 沙箱环境 + 白名单 限制可读写的目录
成本失控 Token 预算上限 每次调用后累计 Token 用量
信息泄露 敏感信息过滤 工具输入输出过滤
无限循环 超时退出机制 timeout = 60s
1
2
3
4
5
6
7
8
9
10
# 安全包装器示例
class SafeAgent:
def __init__(self):
self.max_steps = 10
self.max_tokens = 50000
self.token_used = 0
self.allowed_dirs = ["/project/src"]

def check_permission(self, path: str) -> bool:
return any(path.startswith(d) for d in self.allowed_dirs)

六、Agent 应用场景决策树

用决策树判断是否需要使用 Agent:

1
2
3
4
5
6
7
这个任务是否需要 API 调用或代码执行?
├── 否 → 用普通 Chat 即可
└── 是 → 任务是否需要多步规划和条件判断?
├── 否 → 用 Function Calling 简单调用
└── 是 → 任务是否需要多个专用角色协作?
├── 否 → 用单 Agent(ReAct 模式)
└── 是 → 用多 Agent 框架(CrewAI/LangGraph)

6.1 不适用 Agent 的场景

  • 单次简单查询:查个天气、问个定义 → Chat 就够了
  • 纯信息整理:总结文章、翻译 → 不需要工具调用
  • 确定性计算:1+1=2 → 直接计算即可
  • 模板化生成:每周周报格式固定 → 用脚本而不是 Agent

七、Agent 与 RAG 的协同

Agent 和 RAG 不是互斥方案,而是互补的:

1
2
3
Agent(执行者):需要调用工具完成多步任务
↓ 需要知识
RAG(知识库):为 Agent 提供私有知识支持

例如:一个”代码维护 Agent”可以这样协同:

1
2
3
4
5
用户:"帮我修复这个 bug"
→ Agent 理解任务 → RAG 检索同类 bug 的历史修复记录
→ Agent 参考历史方案 + 当前代码 → 生成修复
→ Agent 调用 git commit 提交修改
→ Agent 调用 CI 触发测试验证

八、Agent 框架选择

框架 语言 特点 适合场景 学习曲线
LangChain Python 生态丰富,文档齐全 快速原型 中等
LangGraph Python 有状态工作流,循环控制 复杂流程编排 较高
CrewAI Python 多 Agent 协作,角色化 团队模拟
AutoGen Python 微软出品,对话式多 Agent 研究实验 中等
OpenCode Agent JS/TS CLI 集成,文件操作 日常开发

学习路线建议

  1. 入门:用 OpenAI/Python 手写一个最小 Agent(上面代码)
  2. 进阶:用 LangChain 快速构建
  3. 专业:用 LangGraph 构建有状态工作流

本章小结

  • Agent 的核心是”思考→行动→观察”的 ReAct 循环
  • Function Calling 是 LLM 调用工具的标准接口,几乎所有主流模型都支持
  • 手写一个最小 Agent 只需要 30 行代码 + 工具定义
  • Agent 的自主性带来效率提升,也带来安全风险——权限控制必不可少
  • 框架推荐:手写入门 → LangChain(进阶)→ LangGraph(专业)
  • 成本监控在 Agent 场景中比单次 LLM 调用更重要

下一篇看 MCP 协议——让 Agent 和工具之间的通信标准化。

ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
分享: